#include "stdafx.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTests {	

TEST_CLASS(StringTest)
{
	public:
		TEST_METHOD(ConvertBool)
		{
			Rz::String strings[] = {
				"true", "tRue", "TRUE", "True",
				"truet", "false", "False", "falSe"
			};

			for (int i = 0; i < RZ_COUNT_OF(strings); i++)
			{
				// Half is true, half is false
				if (i < (RZ_COUNT_OF(strings) / 2))
				{
					Assert::IsTrue(strings[i].Convert<bool>());
				}
				else
				{
					Assert::IsFalse(strings[i].Convert<bool>());
				}
			}
		}

		TEST_METHOD(ConvertDouble)
		{
			Rz::String strings[] = {
				"3", "", "-3gs", "gs3",
				"gs3gs", "-3.1415", "82.14f", "4-92.gs"
			};

			Assert::AreEqual(strings[0].Convert<double>(), 3.0, 0.01);
			Assert::AreEqual(strings[1].Convert<double>(), 0.0, 0.0);
			Assert::AreEqual(strings[2].Convert<double>(), -3.0, 0.01);
			Assert::AreEqual(strings[3].Convert<double>(), 0.0, 0.01);

			Assert::AreEqual(strings[4].Convert<double>(), 0.0, 0.01);
			Assert::AreEqual(strings[5].Convert<double>(), -3.1415, 0.0001);
			Assert::AreEqual(strings[6].Convert<double>(), 82.14, 0.01);
			Assert::AreEqual(strings[7].Convert<double>(), 4.0, 0.1);
		}

		TEST_METHOD(ConvertSigned)
		{
			Rz::String strings[] = {
				"3", "", "-3gs", "gs3",
				"gs3gs", "-3.1415", "82.14f", "4-92.gs"
			};

			Assert::IsTrue(strings[0].Convert<Rz::s32>() == 3);
			Assert::IsTrue(strings[1].Convert<Rz::s32>() == 0);
			Assert::IsTrue(strings[2].Convert<Rz::s32>() == -3);
			Assert::IsTrue(strings[3].Convert<Rz::s32>() == 0);

			Assert::IsTrue(strings[4].Convert<Rz::s32>() == 0);
			Assert::IsTrue(strings[5].Convert<Rz::s32>() == -3);
			Assert::IsTrue(strings[6].Convert<Rz::s32>() == 82);
			Assert::IsTrue(strings[7].Convert<Rz::s32>() == 4);
		}

		TEST_METHOD(ConvertUnsigned)
		{
			Rz::String strings[] = {
				"3", "", "-3gs", "gs3",
				"gs3gs", "-3.1415", "82.14f", "4-92.gs"
			};

			Assert::IsTrue(strings[0].Convert<Rz::u32>() == 3);
			Assert::IsTrue(strings[1].Convert<Rz::u32>() == 0);
			Assert::IsTrue(strings[2].Convert<Rz::u32>() == Rz::u32(-3));
			Assert::IsTrue(strings[3].Convert<Rz::u32>() == 0);

			Assert::IsTrue(strings[4].Convert<Rz::u32>() == 0);
			Assert::IsTrue(strings[5].Convert<Rz::u32>() == Rz::u32(-3));
			Assert::IsTrue(strings[6].Convert<Rz::u32>() == 82);
			Assert::IsTrue(strings[7].Convert<Rz::u32>() == 4);
		}

		TEST_METHOD(CountOf)
		{
			Rz::String s = "The teSt string";
			Rz::String needle = "st";
			
			Assert::IsTrue(s.CountOf('t', Rz::String::Case::NoticeCase) == 3);
			Assert::IsTrue(s.CountOf('t', Rz::String::Case::IgnoreCase) == 4);

			Assert::IsTrue(s.CountOf(needle, Rz::String::Case::NoticeCase) == 1);
			Assert::IsTrue(s.CountOf(needle, Rz::String::Case::IgnoreCase) == 2);
		}

		TEST_METHOD(StartsWithEndsWith)
		{
			Rz::String s = "The teSt string";

			Assert::IsTrue(!s.StartsWith("the", Rz::String::Case::NoticeCase));
			Assert::IsTrue( s.StartsWith("the", Rz::String::Case::IgnoreCase));
			Assert::IsTrue( s.StartsWith("The", Rz::String::Case::NoticeCase));

			Assert::IsTrue(!s.EndsWith("Ring", Rz::String::Case::NoticeCase));
			Assert::IsTrue( s.EndsWith("ring", Rz::String::Case::IgnoreCase));
			Assert::IsTrue( s.EndsWith("ring", Rz::String::Case::NoticeCase));
		}

		TEST_METHOD(Equals)
		{
			Rz::String s = "The teSt string";
			Rz::String s2 = "The test string";

			Assert::IsTrue(s != s2);
			Assert::IsFalse(s == s2);
			Assert::IsFalse(s == static_cast<char*>(NULL));

			Assert::IsTrue(s.Equals(s2, Rz::String::Case::IgnoreCase));
			Assert::IsFalse(s.Equals(s2));
		}

		TEST_METHOD(Erase)
		{
			Rz::String s;

			s = "The teSt string";
			s.Erase(2, 2);
			Assert::IsTrue(s == "ThteSt string");

			s = "The teSt string";
			s.Erase(14, 100);
			Assert::IsTrue(s == "The teSt strin");

			s = "The teSt string";
			s.Erase(0, 100);
			Assert::IsTrue(s.IsEmpty());
		}

		TEST_METHOD(IsHex)
		{
			Rz::String strings[] = {
				"123", "123abC", "fa45", "deadbeef",
				"gs3gs", "-3.1415", "82.14f", "4-92.gs"
			};

			for (int i = 0; i < RZ_COUNT_OF(strings); i++)
			{
				// Half is true, half is false
				if (i < (RZ_COUNT_OF(strings) / 2))
				{
					Assert::IsTrue(strings[i].IsHex());
				}
				else
				{
					Assert::IsFalse(strings[i].IsHex());
				}
			}
		}

		TEST_METHOD(Operators)
		{
			Rz::String strings[] = {
				"abcd", "efgh", "ijkl", "mnop"
			};

			strings[0] = strings[1] + strings[2] + strings[3];
			strings[1] += strings[2] + strings[3];
			strings[2].AddLine(strings[3]);

			Assert::IsTrue(strings[0] == "efghijklmnop");
			Assert::IsTrue(strings[1] == "efghijklmnop");
			Assert::IsTrue(strings[2] == "ijkl\r\nmnop\r\n");
		}

		TEST_METHOD(Split)
		{
			Rz::String s = "one two three four five six";

			Rz::String::Collection c = s.Split(' ', Rz::String::SplitOptions::RemoveEmptyEntries, 4);

			Assert::IsTrue(c[0] == "one");
			Assert::IsTrue(c[1] == "two");
			Assert::IsTrue(c[2] == "three");
			Assert::IsTrue(c[3] == "four five six");

			c = s.Split(" ", Rz::String::SplitOptions::RemoveEmptyEntries, 4);

			Assert::IsTrue(c[0] == "one");
			Assert::IsTrue(c[1] == "two");
			Assert::IsTrue(c[2] == "three");
			Assert::IsTrue(c[3] == "four five six");

			c = s.Split({ ' ', 'e' }, Rz::String::SplitOptions::RemoveEmptyEntries, 4);

			Assert::IsTrue(c[0] == "on");
			Assert::IsTrue(c[1] == "two");
			Assert::IsTrue(c[2] == "thr");
			Assert::IsTrue(c[3] == "e four five six");
		}
};

}
